package com.easy.cloud.web.module.certification.biz.service.certification.company.client;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.easy.cloud.web.component.core.response.HttpResult;
import com.easy.cloud.web.module.certification.api.enums.CompanyCertificationClientEnum;
import com.easy.cloud.web.module.certification.biz.service.certification.company.CompanyCertificationProperties;
import com.easy.cloud.web.module.certification.biz.service.certification.company.ICompanyCertificationClient;
import com.easy.cloud.web.module.certification.biz.service.certification.company.entity.CompanyCertificationBody;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 腾讯云认证
 * <p>文档：https://cloud.tencent.com/document/product/1007/39765</p>
 *
 * @author GR
 * @date 2024/2/19 19:38
 */
@Slf4j
@Service
public class TencentCompanyCertificationClient implements ICompanyCertificationClient {

    @Autowired
    private CompanyCertificationProperties companyCertificationProperties;

    @Override
    public CompanyCertificationClientEnum client() {
        return CompanyCertificationClientEnum.TENCENT;
    }

    @Override
    public HttpResult<Object> certification(CompanyCertificationBody companyCertificationBody) {
        String failMessage = "";
        try {
            Calendar cd = Calendar.getInstance();
            SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
            sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
            String datetime = sdf.format(cd.getTime());
            // 签名
            String auth = calcAuthorization(companyCertificationProperties.getSource(),
                    companyCertificationProperties.getSecretId(),
                    companyCertificationProperties.getSecretKey(),
                    datetime);
            // 请求头
            Map<String, String> headers = new HashMap<>();
            headers.put("X-Source", companyCertificationProperties.getSource());
            headers.put("X-Date", datetime);
            headers.put("Authorization", auth);

            // 查询参数
            Map<String, String> queryParams = new HashMap<>();
            queryParams.put(companyCertificationProperties.getUsciKey(), companyCertificationBody.getUsci());
            queryParams.put(companyCertificationProperties.getCompanyNameKey(), companyCertificationBody.getCompanyName());
            queryParams.put(companyCertificationProperties.getLegalPersonKey(), companyCertificationBody.getUserName());
            // url参数拼接
            String url = companyCertificationProperties.getUrl();
            if (!queryParams.isEmpty()) {
                url += "?" + urlencode(queryParams);
            }

            HttpRequest httpRequest = HttpUtil.createGet(url);
            httpRequest.headerMap(headers, true);
            HttpResponse httpResponse = httpRequest.execute();
            JSONObject jsonObject = JSONUtil.parseObj(httpResponse.body());
            JSONObject data = jsonObject.getJSONObject("data");
            if (Objects.nonNull(data)) {
                String result = data.getStr("result");
                if (StrUtil.isNotBlank(result) && companyCertificationProperties.getResultCode().equals(result)) {
                    log.info("企业三要素认证成功：{}" + httpResponse.body());
                    return HttpResult.ok();
                }
            }

            failMessage = httpResponse.body();
        } catch (Exception exception) {
            failMessage = exception.getMessage();
        }

        failMessage = StrUtil.format("企业三要素认证失败：{}", failMessage);
        log.warn(failMessage);
        return HttpResult.fail(failMessage);
    }

    public String calcAuthorization(String source, String secretId, String secretKey, String datetime)
            throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
        String signStr = "x-date: " + datetime + "\n" + "x-source: " + source;
        Mac mac = Mac.getInstance("HmacSHA1");
        Key sKey = new SecretKeySpec(secretKey.getBytes("UTF-8"), mac.getAlgorithm());
        mac.init(sKey);
        byte[] hash = mac.doFinal(signStr.getBytes("UTF-8"));
        String sig = Base64.encode(hash);
        return "hmac id=\"" + secretId + "\", algorithm=\"hmac-sha1\", headers=\"x-date x-source\", signature=\"" + sig + "\"";
    }

    public String urlencode(Map<?, ?> map) throws UnsupportedEncodingException {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<?, ?> entry : map.entrySet()) {
            if (sb.length() > 0) {
                sb.append("&");
            }
            sb.append(String.format("%s=%s",
                    URLEncoder.encode(entry.getKey().toString(), "UTF-8"),
                    URLEncoder.encode(entry.getValue().toString(), "UTF-8")
            ));
        }
        return sb.toString();
    }
}
